package xcmg.device.web.warehouse;

import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import xcmg.device.dao.entity.PriMaterialsDO;
import xcmg.device.dao.entity.warehouse.WarehouseDO;
import xcmg.device.dao.entity.warehouse.allot.RegionAllotDO;
import xcmg.device.infra.AuthCode;
import xcmg.device.infra.BasicController;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.enums.PurchaseStatus;
import xcmg.device.service.ExternalParamCheckService;
import xcmg.device.service.vo.ExternalParamCheckVO;
import xcmg.device.service.vo.FunctionResult;
import xcmg.device.service.vo.delivery.ManualFinishVO;
import xcmg.device.service.vo.warehouse.allot.RegionAllotAddVO;
import xcmg.device.service.vo.warehouse.allot.RegionAllotDetailVO;
import xcmg.device.service.vo.warehouse.allot.RegionAllotVO;
import xcmg.device.service.warehouse.allot.RegionAllotDetailService;
import xcmg.device.service.warehouse.allot.RegionAllotService;
import yb.ecp.fast.infra.annotation.FastMappingInfo;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.infra.log.LogHelper;

import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@RestController
@RequestMapping("/regionAllot")
public class RegionAllotController extends BasicController {
    @Autowired
    private RegionAllotService regionAllotService;

    @Autowired
    private ExternalParamCheckService externalParamCheckService;

    @Autowired
    private RegionAllotDetailService regionAllotDetailService;

    @Autowired
    private RestTemplate restTemplate;

//    @Autowired
//    private XmlMapper xmlMapper;

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @ApiOperation(value = "增加区域调拨记录")
    @FastMappingInfo(needLogin = true, code = AuthCode.RegionAllot.ADD)
    public ActionResult warehouse(@RequestBody RegionAllotAddVO regionAllotAddVO) throws Exception {
        if (null == regionAllotAddVO) {
            return actionResult(ErrorCode.IllegalArument);
        }
        ErrorCode errorCode = regionAllotService.add(regionAllotAddVO, getUserId(), getOrgId());
        return actionResult(errorCode);
    }

    @RequestMapping(value = "/update", method = RequestMethod.POST)
    @ApiOperation(value = "更新区域调拨记录")
    @FastMappingInfo(needLogin = true, code = AuthCode.RegionAllot.EDIT)
    public ActionResult update(@RequestBody RegionAllotAddVO regionAllotAddVO) throws Exception {
        FunctionResult result = new FunctionResult();
        ErrorCode errorCode;
        try {
            errorCode = regionAllotService.update(regionAllotAddVO, getOrgId());
            result.setCode(errorCode);
            result.setValue(errorCode.getDesc());
        } catch (Exception exc) {
            LogHelper.monitor(getExceptionAllinformation(exc));
            return new ActionResult(1, exc.getMessage());
        }
        return actionResult(result.getCode(), result.getValue());
    }

    @RequestMapping(value = "/adjust", method = RequestMethod.POST)
    @FastMappingInfo(needLogin = true, code = AuthCode.RegionAllot.EDIT)
    public ActionResult adjust(@RequestBody RegionAllotAddVO regionAllotAddVO) {
        ErrorCode errorCode;
        try {
            errorCode = regionAllotService.adjust(regionAllotAddVO, getOrgId());
        } catch (Exception exc) {
            LogHelper.monitor(getExceptionAllinformation(exc));
            return new ActionResult(1, exc.getMessage());
        }
        return actionResult(errorCode);
    }

    @RequestMapping(value = "/remove", method = RequestMethod.POST)
    @ApiOperation("区域调拨记录删除")
    @FastMappingInfo(needLogin = true, code = AuthCode.RegionAllot.DEL)
    public ActionResult remove(@RequestBody String[] ids) throws Exception {
        if (ids == null || ids.length == 0) {
            return actionResult(ErrorCode.IllegalArument);
        }
        return actionResult(regionAllotService.remove(Arrays.asList(ids), getOrgId()));
    }

    @RequestMapping(value = "/item", method = RequestMethod.GET)
    @ApiOperation(value = "查找单条记录详情")
    @FastMappingInfo(needLogin = true)
    public ActionResult item(String id) throws Exception {
        return actionValueResult(regionAllotService.findByPK(id, "id", getOrgId()));
    }

    @RequestMapping(value = "/itemByNo", method = RequestMethod.GET)
    @ApiOperation(value = "查找单条记录详情")
    @FastMappingInfo(needLogin = true)
    public ActionResult itemByNo(String allotOrder) throws Exception {
        return actionValueResult(regionAllotService.findByPK(allotOrder, "allotOrder", getOrgId()));
    }

    @RequestMapping(value = "/list", method = RequestMethod.POST)
    @ApiOperation("查询区域调拨记录列表")
    @FastMappingInfo(needLogin = true)
    public ActionResult list(@RequestBody SearchCommonVO<RegionAllotVO> condition) throws Exception {
        RegionAllotVO regionAllotVO = condition.getFilters();
        if (regionAllotVO == null) {
            regionAllotVO = new RegionAllotVO();
        }
        regionAllotVO.setOrgId(getOrgId());
        condition.setFilters(regionAllotVO);
        PageCommonVO pageCommonVO = regionAllotService.list(condition, getDeptId());
        return actionValueResult(pageCommonVO.getPageInfo());
    }

    @RequestMapping(value = "/export", method = RequestMethod.POST)
    @ApiOperation("导出区域调拨记录列表")
    @FastMappingInfo(needLogin = true, code = AuthCode.RegionAllot.EXPORT)
    public void export(String[] ids) throws Exception {
        regionAllotService.export(Arrays.asList(ids));
    }

    @RequestMapping(value = "/exportAll", method = RequestMethod.POST)
    @ApiOperation("导出全部区域调拨记录列表")
    @FastMappingInfo(needLogin = true, code = AuthCode.RegionAllot.EXPORT)
    public void exportAll(RegionAllotVO condition) throws Exception {
        condition.setOrgId(getOrgId());
        regionAllotService.exportAll(condition);
    }

    @ResponseBody
    @RequestMapping(value = "/import", method = RequestMethod.POST)
    @ApiOperation("零件批量导入")
    @FastMappingInfo(needLogin = true)
    public ActionResult importExcel(HttpServletRequest request) throws Exception {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile file = multipartRequest.getFile(multipartRequest.getFileNames().next());
        String fileName = file.getOriginalFilename();
        FunctionResult<String> result = new FunctionResult<>();
        if (!fileName.trim().endsWith(".xls")) {
            result.setCode(ErrorCode.ImportExcelEndWithXLS);
        } else {
            InputStream in = file.getInputStream();
            result = regionAllotService.importExcel(in, request.getParameter("x-warehouseCode"), request.getParameter("x-areaCode"), getOrgId());
        }
        return actionResult(result.getCode(), result.getValue());
    }

    @RequestMapping(value = "/download", method = RequestMethod.POST)
    @ApiOperation("下载零件批量导入模板")
    @FastMappingInfo(needLogin = true)
    public void download() throws Exception {
        regionAllotService.download();
    }

    @RequestMapping(value = "/manualFinishIn", method = RequestMethod.POST)
    @ApiOperation("强制完成单据")
    public ActionResult manualFinishIn(@RequestBody ManualFinishVO manualFinishVO) throws Exception {
        return actionResult(regionAllotService.manualFinish(manualFinishVO.getBillNo(), manualFinishVO.getMaterialsNo(), getOrgId(), 0));
    }


    @RequestMapping(value = "/manualFinishOut", method = RequestMethod.POST)
    @ApiOperation("强制完成单据")
    public ActionResult manualFinishOut(@RequestBody ManualFinishVO manualFinishVO) throws Exception {
        return actionResult(regionAllotService.manualFinishOut(manualFinishVO, getOrgId()));
    }

    @RequestMapping(value = "/auditPass", method = RequestMethod.POST)
    @FastMappingInfo(needLogin = true, code = AuthCode.RegionAllot.AUDIT)
    public ActionResult auditPass(@RequestBody RegionAllotAddVO regionAllotAddVO) throws Exception {
        regionAllotAddVO.getHeaderInfo().setBillStatus(PurchaseStatus.AuditPass.toString());
        return actionResult(regionAllotService.auditBill(regionAllotAddVO, getUserId(), getOrgId()));
    }

    @RequestMapping(value = "/auditRefused", method = RequestMethod.POST)
    @FastMappingInfo(needLogin = true, code = AuthCode.RegionAllot.AUDIT)
    public ActionResult auditRefused(@RequestBody RegionAllotAddVO regionAllotAddVO) throws Exception {
        regionAllotAddVO.getHeaderInfo().setBillStatus(PurchaseStatus.AuditRefused.toString());
        return actionResult(regionAllotService.auditBill(regionAllotAddVO, getUserId(), getOrgId()));
    }

    /**
     * 对外提供添加接口
     *
     * @param model
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/addRegionAllot", method = RequestMethod.POST)
    //@FastMappingInfo(needLogin = true)
    public ActionResult addRegionAllot(@RequestBody RegionAllotAddVO model) throws Exception {
        if (null == model || null == model.getHeaderInfo()) {
            return actionResult(ErrorCode.IllegalArument);
        }
        LogHelper.monitor("addRegionAllot接口入参：" + model.toString());

        ActionResult result;
        try {
            // 如果是塔机的sapCode则需要根据调入/调出仓库名称获取调入/调出仓库的库区和仓库
            ActionResult actionResult = tjParamHandle(model);
            if (!successActionResult(actionResult)) {
                return actionResult;
            }
            externalParamCheckService.checkParam(fillNeedCheckParam(model));
            result = regionAllotService.addRegionAllot(model);
        } catch (Exception e) {
            return actionResult(ErrorCode.Failure, e.getMessage());
        }
        return result;
    }


    /**
     * 对外提供添加接口
     *
     * @param model
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/addRegionAllot4Tj", method = RequestMethod.POST)
    //@FastMappingInfo(needLogin = true)
    public ActionResult addRegionAllot4Tj(@RequestBody RegionAllotAddVO model) throws Exception {
        if (null == model || null == model.getHeaderInfo()) {
            return actionResult(ErrorCode.IllegalArument);
        }
        LogHelper.monitor("addRegionAllot接口入参：" + model.toString());

        //crmOrder重复单号校验
        ActionResult crmOrderDulpCheck = crmOrderDulpCheck(model);
        if (crmOrderDulpCheck != null && successActionResult(crmOrderDulpCheck)) {
            return crmOrderDulpCheck;
        }
        ActionResult result;
        try {
            // 如果是塔机的sapCode则需要根据调入/调出仓库名称获取调入/调出仓库的库区和仓库
            ActionResult actionResult = tjParamHandle(model);
            if (!successActionResult(actionResult)) {
                return actionResult;
            }
            externalParamCheckService.checkParam(fillNeedCheckParam(model));
            result = regionAllotService.addRegionAllot4Tj(model);
        } catch (Exception e) {
            return actionResult(ErrorCode.Failure, e.getMessage());
        }
        return result;
    }


    /**
     * 判断crmOrder是否已经存在记录，如果存在则返回操作成功，同时返回存在的PMS编号--
     * 这么返回的原因crm调接口大多加在签核流程里面，多次点击触发接口，返回已存在，会影响签核的动作（具体可以问瑞泰-黄远辉）
     * 返回null代表流程可以继续往下走，返回code=0表示已经存在数据，直接返回已存在的数据
     */
    private ActionResult crmOrderDulpCheck(RegionAllotAddVO model) {
        String crmOrder = model.getHeaderInfo().getCrmOrder();
        if (StringUtils.isEmpty(crmOrder)) {
            return actionResult(ErrorCode.Failure, "crm订单号不能为空", "crm订单号不能为空");
        }
        List<RegionAllotDO> schedules = regionAllotService.getRegionAllotByCrmOrder(crmOrder);
        if (!CollectionUtils.isEmpty(schedules)) {
            return actionResult(ErrorCode.Success, "CRM单号已存在", schedules.get(0).getAllotOrder());
        }
        return null;
    }


    /**
     * 塔机请求的时候传过来的是仓库的名称，需要根据仓库的名称查询转换获取仓库的编码
     * 这里注意库区的编码也直接用仓库的编码赋值（胡彬做数据的时候会把两个编码值做成一样的）
     *
     * @param model
     */
    private ActionResult tjParamHandle(RegionAllotAddVO model) throws Exception {
        if (model == null) {
            return actionResult(ErrorCode.Success);
        }
        RegionAllotVO headerInfo = model.getHeaderInfo();
        String sapCode = headerInfo.getSapCode();
        //如果sapCode为空或者不是塔机的则直接返回
        if (StringUtils.isEmpty(sapCode) || !"2130".equals(sapCode)) {
            return actionResult(ErrorCode.Success);
        }
        String orgId = externalParamCheckService.getOrgIdBySapCode(sapCode);
        //塔机的特殊处理根据调入仓库/调出仓库名称获取调入仓库调出仓库编码==========start==============
        String inWarehouse = headerInfo.getInWarehouse();
        String outWarehouse = headerInfo.getOutWarehouse();
        if (StringUtils.isEmpty(inWarehouse) || StringUtils.isEmpty(outWarehouse)) {
            actionResult(ErrorCode.Failure, "调入/调出仓库名称不能为空", "调入/调出仓库名称不能为空");
        }
        //
        List<WarehouseDO> inwarehouse = regionAllotService.getWareHousesByOrgAndDescription(orgId, inWarehouse);
        List<WarehouseDO> outwarehouse = regionAllotService.getWareHousesByOrgAndDescription(orgId, outWarehouse);
        if (inwarehouse.size() < 1) {
            return actionResult(ErrorCode.Failure, "调入仓库名称:" + inWarehouse + "无法匹配仓库", "调入仓库名称:" + inWarehouse + "无法匹配仓库");
        }
        if (outwarehouse.size() < 1) {
            return actionResult(ErrorCode.Failure, "调出仓库名称:" + inWarehouse + "无法匹配仓库", "调出仓库名称:" + inWarehouse + "无法匹配仓库");
        }
        //默认参数赋值
        tjDefaultParamAssemble(model);
        String inLocal = inwarehouse.get(0).getWarehouseCode();
        String inArea = inLocal;
        String outLocal = outwarehouse.get(0).getWarehouseCode();
        String outArea = outLocal;
        headerInfo.setInLocation(inLocal);
        headerInfo.setInArea(inArea);
        headerInfo.setSapInArea(inArea);
        headerInfo.setOutLocation(outLocal);
        headerInfo.setOutArea(outArea);
        headerInfo.setSapOutArea(outArea);
        //塔机的特殊处理根据调入仓库/调出仓库名称获取调入仓库调出仓库编码==========end==============
        //拼接零件的单位信息unit
        List<RegionAllotDetailVO> detailList = model.getDetailList();
        for (RegionAllotDetailVO material : detailList) {
            String materialNo = material.getMaterialNo();
            PriMaterialsDO materialsInfo = externalParamCheckService.getMaterialsInfo(materialNo);
            if (materialsInfo == null) {
                continue;
            }
            String unit = materialsInfo.getUnit();
            material.setUnit(unit);
            String materialsDes = materialsInfo.getMaterialsDes();
            if (!StringUtils.isEmpty(materialsDes)) {
                material.setMaterialName(materialsDes);
            }
        }
        //拼保存的初始状态描述
        String billStatus = headerInfo.getBillStatus();
        String statusDesc = billStatusConvert(billStatus);
        headerInfo.setStatusDesc(statusDesc);
        return actionResult(ErrorCode.Success);
    }

    /**
     * 塔机创建调拨单默认字段赋值
     */
    private void tjDefaultParamAssemble(RegionAllotAddVO model) {
        RegionAllotVO headerInfo = model.getHeaderInfo();
        headerInfo.setCreateId("477477706045325312");
        headerInfo.setCreateName("接口用户");
        headerInfo.setDeptId("455404133906644992");
        headerInfo.setDeptName("服务部");
        headerInfo.setStatusDesc("待审核");
        headerInfo.setDispatcherId("477477706045325312");
        headerInfo.setDispatcherName("接口用户");
    }

    private String billStatusConvert(String billStatus) {
        if (StringUtils.isEmpty(billStatus)) {
            return null;
        }
        try {
            Integer billStatusInt = Integer.valueOf(billStatus);
            switch (billStatusInt) {
                case 1:
                    return "待审核";
                default:
                    return null;
            }
        } catch (Exception e) {
            return null;
        }

    }

    private ExternalParamCheckVO fillNeedCheckParam(RegionAllotAddVO model) throws Exception {
        if (CollectionUtils.isEmpty(model.getDetailList())) {
            throw new Exception("缺少零件信息");
        }
        ExternalParamCheckVO param = new ExternalParamCheckVO();
        List<String> materialsNos = new ArrayList<>();
        for (RegionAllotDetailVO detailVO : model.getDetailList()) {
            materialsNos.add(detailVO.getMaterialNo());
        }
        param.setMaterialsNos(materialsNos);
        param.setInArea(model.getHeaderInfo().getInArea());
        param.setInLocation(model.getHeaderInfo().getInLocation());
        param.setOutArea(model.getHeaderInfo().getOutArea());
        param.setOutLocation(model.getHeaderInfo().getOutLocation());
        param.setSapCode(model.getHeaderInfo().getSapCode());
        return param;
    }

    private String getExceptionAllinformation(Exception ex) {
        String sOut = "\r\n";
        StackTraceElement[] trace = ex.getStackTrace();
        for (StackTraceElement s : trace) {
            sOut += "\tat " + s + "\r\n";
        }
        return sOut;
    }

    /*@GetMapping("/testCrmInterface")
    public void testCrmInterface(String materialNo,String allotOrder) throws Exception {
        regionAllotDetailService.testCrmInterface(materialNo,allotOrder,getOrgId());
    }*/

    //    /**
//     * 用于在同步crm失败的情况下，手动调用该接口重新同步
//     *
//     * @param ids
//     * @return
//     * @throws Exception
//     */
//    @RequestMapping("/syncCrm")
//    @FastMappingInfo(needLogin = true)
//    public ActionResult syncCrm(@RequestBody String[] ids) throws Exception {
//        String orgId = getOrgId();
//        for (String id : ids) {
//            regionAllotService.syncCrm(id, orgId);
//        }
//        return actionResult(ErrorCode.Success);
//    }
//    @GetMapping("/testSfApi")
//    public ResponseEntity testSfApi() throws IOException {
//
//        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//
//        XmlMapper xmlMapper = new XmlMapper();
//        xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//        xmlMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false);
//        xmlMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//        xmlMapper.setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE);
//        xmlMapper.enable(MapperFeature.USE_STD_BEAN_NAMING);
//
//        PurchaseOrderServiceDO purchaseOrderServiceDO = new PurchaseOrderServiceDO();
//        purchaseOrderServiceDO.setService("PURCHASE_ORDER_SERVICE");
//        purchaseOrderServiceDO.setLang("zh-CN");
//
//        SfCheckDO sfCheckDO = new SfCheckDO();
//        sfCheckDO.setAccessCode("bvW2Fcx8Hb1OYzZaL2mY8A==");
//        sfCheckDO.setCheckword("Pa2zfPtcCIvmhxYkfw5Bj6JgPmx63s4i");
//        purchaseOrderServiceDO.setSfCheckDO(sfCheckDO);
//
//        PurchaseOrderRequestDO purchaseOrderRequestDO = new PurchaseOrderRequestDO();
//        purchaseOrderRequestDO.setCompanyCode("COMMONCOMPANY");
//        List<PurchaseOrderDO> purchaseOrderDOS = new ArrayList<>();
//        PurchaseOrderDO purchaseOrderDO = new PurchaseOrderDO();
//        purchaseOrderDO.setErpOrder("123");
//        purchaseOrderDO.setErpOrderType("1");
//        purchaseOrderDO.setWarehouseCode("571DCF");
//        purchaseOrderDO.setOrderDate(simpleDateFormat.format(new Date()));
//        purchaseOrderDO.setScheduledReceiptDate(simpleDateFormat.format(new Date()));
//        purchaseOrderDO.setVendorCode("123456");
//
//        List<PurchaseOrderItemDO> itemDOList = new ArrayList<>();
//        PurchaseOrderItemDO itemDO = new PurchaseOrderItemDO();
//        itemDO.setSkuNo("11111");
//        itemDO.setLot("1111");
//        itemDO.setQty(new BigDecimal(0));
//        itemDOList.add(itemDO);
//        purchaseOrderDO.setItemList(itemDOList);
//
//        purchaseOrderDOS.add(purchaseOrderDO);
//        purchaseOrderRequestDO.setPurchaseOrderDOList(purchaseOrderDOS);
//        SfRequestBodyDO sfRequestBodyDO = new SfRequestBodyDO();
//        sfRequestBodyDO.setPurchaseOrderRequestDO(purchaseOrderRequestDO);
//        purchaseOrderServiceDO.setSfRequestBodyDO(sfRequestBodyDO);
//
//        String xml = xmlMapper.writeValueAsString(purchaseOrderServiceDO);
//        xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + xml;
//        //Object obj = sfOmsClient.OmsCommons(xml);
//        //HttpHeaders headers = new HttpHeaders();
//        //headers.setContentType(MediaType.APPLICATION_XML);
//        //HttpEntity<String> formEntity = new HttpEntity<>(xml, headers);
//        //ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://bsp-oisp.sf-express.com/bsp-wms/OmsCommons", formEntity, String.class);
//
//        String xmlToken = xml + "W5170454336";
//        System.out.println(xml);
//        String md5DigestAsHex = DigestUtils.md5DigestAsHex(xmlToken.getBytes());
//        System.out.println(md5DigestAsHex);
//        String base64Encord = new BASE64Encoder().encode(md5DigestAsHex.getBytes());
//        System.out.println(base64Encord);
//        String urlEncord = URLEncoder.encode(base64Encord, "utf-8");
//        System.out.println(urlEncord);
//        //Object o = sfOmsClient.OmsCommons(URLEncoder.encode(xml, "utf-8"), urlEncord);
//
//        MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
//        map.add("logistics_interface", xml);
//        map.add("data_digest", base64Encord);
//        HttpHeaders headers = new HttpHeaders();
//        headers.add("Content-Type", "application/x-www-form-urlencoded");
//        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
//        ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity("http://bsp.sit.sf-express.com:8080/bsp-wms/OmsCommons", request, String.class);
//
//        SfResponseDO sfResponseDO = xmlMapper.readValue(stringResponseEntity.getBody(), SfResponseDO.class);
//
//
//        return ResponseEntity.ok(sfResponseDO);
//    }
}
